
#include "precompiled.h"
#include "declarativeenvironmentex.h"

#include <QtDeclarative>
#include "helper.h"
#include <extensions/plugin.h>
#include <extensions/application.h>
#include <extensions/mainwindow.h>
#include "contextimpl.h"
#include "tasks.h"
#include <script/objects/optra.h>

class DeclarativeEnvironmentExPrivate{
	public:
	DeclarativeEnvironmentExPrivate() :engine(new QDeclarativeEngine)
	,component(0), object(0)
	{
		QString path = Engine::instance()->environment()->expandPath(Opl::Helpers::Support::Environment::script_sdk_include, "");
		LI.Trace() << "Add Import Path:" << path;
		engine->addImportPath(path);

		//path = Engine::instance()->environment()->expandPath(Opl::Helpers::Support::Environment::script_sdk_include, "sdk/gui/controls");
		//LI.Trace() << "Add Import Path:" << path;
		//engine->addImportPath(path);
	}
		~DeclarativeEnvironmentExPrivate()
		{			
			delete object;
			delete component;
			delete engine;
		}

		void reload()
		{
			delete object;
			object = 0;

			//delete engine;
			//engine = new QDeclarativeEngine;

			delete component;
			component = new QDeclarativeComponent(engine);
		}

		QUrl url;
		QDeclarativeEngine* engine;
		QDeclarativeComponent* component;
		QString errorString;
		QObject* object;

};

DeclarativeEnvironmentEx::DeclarativeEnvironmentEx(Opl::Core::EntityObject *parent) :
	Opl::Scripting::DeclarativeEnvironment(parent), O_PRIVATE_CREATE(DeclarativeEnvironmentEx)
{
	O_D(DeclarativeEnvironmentEx);

	LI.Trace() << "Create Declarative Environment:" << toString();
	LI.Trace() << "Registring types.";

	qmlRegisterType<OptraCore>("Optra", 1, 0, "Optra");
	//qmlRegisterType<ContextImpl>("Optra", 1, 0, "Context");
	qmlRegisterType<Optra::Extensions::MainWindow>("Optra", 1, 0, "MainWindow");	
	qmlRegisterType<TaskEntry>("Optra", 1, 0, "Task");

	//qmlRegisterUncreatableType<Optra::Extensions::Context>("Optra", 1, 0, "Optra::Extensions::Context", "Read only property");
	qmlRegisterInterface<Optra::Extensions::Context>("Context");

        qmlRegisterType<Optra::Extensions::Plugin>("Optra", 1, 0, "Plugin");
        qmlRegisterType<Optra::Extensions::Application>("Optra", 1, 0, "Application");
		 
	d->reload(); 
	LI.Trace() << "Creating Environment done.";

}


DeclarativeEnvironmentEx::~DeclarativeEnvironmentEx()
{
	O_PRIVATE_DELETE;
}

QObject* DeclarativeEnvironmentEx::object()const
{
	O_C(DeclarativeEnvironmentEx);
	return d->object;
}

QDeclarativeComponent* DeclarativeEnvironmentEx::component()
{
	O_D(DeclarativeEnvironmentEx);
	return d->component;
}

QString DeclarativeEnvironmentEx::errorString()
{
	O_D(DeclarativeEnvironmentEx);
	return d->errorString;
}

void DeclarativeEnvironmentEx::registerObject(const QString& name, Opl::Core::EntityObject* object, const QString& package/* = ""*/)
{
	Q_ASSERT(object);
	O_D(DeclarativeEnvironmentEx);	
	LI.Trace() << "Registering object:" << name << "{Type:" << object->toString() << "}";	

//	QStringList part = package.split(".", QString::SkipEmptyParts);
//    QDeclarativeContext* co = d->engine->rootContext();
//    foreach(QString p, part){
//        if (!co->contextProperty(p).isObject()){

//            co->setContextProperty(p, );
//            co.setProperty(p, o);
//            co = o;
//        }
//    }

//    QScriptValue obj = d->engine->newQObject(object);
//    co.setProperty(name, obj);
	d->engine->rootContext()->setContextProperty(name, (QObject*)object);
}

QDeclarativeItem* DeclarativeEnvironmentEx::declarativeItem()
{
	O_D(DeclarativeEnvironmentEx);
	return qobject_cast<QDeclarativeItem*>(d->object);
}

bool DeclarativeEnvironmentEx::initialize(const QUrl& url, bool newWindow/* = false*/)
{
	O_D(DeclarativeEnvironmentEx);
	setUrl(url);
	LI.Debug() << "initialize script:" << d->url.toString();
	d->reload();
	d->errorString.clear();
	d->component->loadUrl(d->url);
	if (d->component->status() == QDeclarativeComponent::Error)
	{
		d->errorString = d->component->errorString();
		LI.Error() << "Error while executing:" << d->errorString;
		return false;
	}
	d->object = d->component->create();

	return true;  
}
 
QObject* DeclarativeEnvironmentEx::exec()
{
	O_D(DeclarativeEnvironmentEx);
	LI.Debug() << "Execute script:" << d->url.toString();
	return d->object;
}

void DeclarativeEnvironmentEx::setUrl(const QUrl& url)
{
	O_D(DeclarativeEnvironmentEx);
	d->url = url;
}

void DeclarativeEnvironmentEx::stop()
{
	O_D(DeclarativeEnvironmentEx);
	d->reload();
}

void DeclarativeEnvironmentEx::reload()
{
	O_D(DeclarativeEnvironmentEx);
	exec();
}
